package cn.melonlib.cores.jpa.model.bean.adapter;

import cn.melonlib.cores.commons.comp.enums.QueryType;
import cn.melonlib.cores.commons.comp.utils.HibernateQlParamsTool;
import cn.melonlib.cores.jpa.model.bean.OffsetQuery;
import cn.melonlib.cores.jpa.model.bean.Searcher;
import cn.melonlib.cores.jpa.model.bean.impl.PaginationList;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.io.Serializable;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class OffsetSearcher<DATA> implements Searcher<PaginationList<DATA>, OffsetQuery> {
    @Override
    public PaginationList<DATA> search(OffsetQuery query, EntityManager entityManager) {
        if(query.getQueryType().equals(QueryType.JPA)){
            Query countQuery=this.createSearchCount(entityManager,query.getEntityClass(),query.getFilter());
            Query searchQuery=this.createSearchQuery(entityManager,query.getEntityClass(),query.getFilter(),query.getOrderBy());
            searchQuery.setFirstResult((int)query.getOffset());
            searchQuery.setMaxResults((int)query.getLimit());
            return PaginationList.createOffset(searchQuery.getResultList(),query,((Number)countQuery.getSingleResult()).longValue());
        }else{
            Query q=entityManager.createQuery(query.getContent());
            HibernateQlParamsTool.setQueryParam(q,query.getParams());
            q.setFirstResult((int)query.getOffset());
            q.setMaxResults((int)query.getLimit());
            List<DATA> result= q.getResultList();
            return PaginationList.createOffset(result,query,this.countHqlRes(query.getContent(),query.getParams(),entityManager));
        }
    }

    @Override
    public Class<OffsetQuery> registerType() {
        return OffsetQuery.class;
    }
    public static final Pattern cntRegex=Pattern.compile("^(select .+? )?(from .+)$");
    private int countHqlRes(String hql, List<? extends Serializable> params, EntityManager entityManager){
        Matcher m=cntRegex.matcher(hql);
        if(m.matches()){
            String cnthql="select count(*) "+ m.group(2);
            if(cnthql.indexOf("order by")!=-1){
                cnthql=cnthql.substring(0, cnthql.indexOf("order "));
            }
            Query query=entityManager.createQuery(cnthql);
            HibernateQlParamsTool.setQueryParam(query, params);
            return ((Number) query.getResultList().get(0)).intValue();
        }else{
            return 0;
        }
    }


}
